前面做了幾個範例,今天我們來做一個登入頁面,試試看 vue-router 轉跳頁面以及 vuex 如何驗證搭配 Promise 使用。
Template use bootstrap example signin
login 算是全域行為,所以就不細分成 module 直接設計在 root 裡面。
有時候發出去的 action 是非同步事件,可是 vue UI 需要知道事件回傳的狀態是 success
或 error
?
如果,這樣的狀態不太需要存在 vuex 裡面。
我們就可以利用 ES6 Promise 包裝,回傳 resolve
或 reject
來反應 UI 變化。
resolve
結果會在 then
裡面收到,reject
結果會在 catch
裡面收到。export const actions = {
// login
actionLogin ({ commit }, { email, password}) {
// 目前沒找到比較好的範例 API,因此使用延遲 1.5s 模擬 ajax 以及簡單驗證。
console.log('1. actionLogin');
commit(types.LOADING, true); // 打開遮罩
// 使用 Promise 包裝 API
return new Promise((resolve, reject) => {
setTimeout(() => {
if (email === 'vue_vuex2@ironman2017.tw' && password === '123') {
console.log('2. Promise resolve');
commit(types.LOADING, false); // 關閉遮罩
resolve(); // resolve 結果會在 then 裡面收到
}
// error
else {
commit(types.LOADING, false); // 關閉遮罩
reject(); // reject 結果會在 catch 裡面收到
}
}, 1500);
});
}
}
使用 $router.push 轉跳到 hello Page
// path
$router.push('/hello');
// name
$router.push({name: 'hello'});
<template>
<div id="login">
<img src="static/img/ironman2017.jpg" class="responsive-img">
<div class="container">
<div class="form-signin">
<h2 class="form-signin-heading">Please sign in</h2>
<label for="email" class="sr-only">Email address</label>
<input
v-model="email"
type="email"
id="email"
class="form-control"
placeholder="Email address" required autofocus />
<label for="inputPassword" class="sr-only">Password</label>
<input
v-model="password"
@keyup.enter="login"
type="password"
id="inputPassword"
class="form-control"
placeholder="Password" required />
<button
class="btn btn-lg btn-primary btn-block"
type="submit"
@click="login">
Sign in
</button>
<br/>
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
data () {
return {
email: 'vue_vuex2@ironman2017.tw',
password: '',
}
},
methods: {
login () {
// 因為 action 包裝了 Promise 所以可以使用 then 和 catch 來接收非同步回傳狀態
this.$store.dispatch('actionLogin', {
email: this.email,
password: this.password
})
.then(() => { // 接收 resolve
console.log('3. get Promise resolve');
setTimeout(() => {
// 使用 $router.push 轉跳到 hello Page
this.$router.push('/hello');
}, 1000);
})
.catch(() => { // 接收 reject
console.log('error get Promise reject!');
});
}
}
}
</script>
順序 | 框架 | 事件 | 回傳 |
---|---|---|---|
1 | Vue | 按下登入按鈕 發動 action | |
2 | vuex | action 使用 ajax 調用 API | |
3-1 | vuex | ajax response success |
resolve |
4-1 | Vue | action method .then 接收 resolve |
|
3-2 | vuex | ajax response error |
reject |
4-2 | Vue | action method .catch 接收 reject |
實作小範例入門 Vue & Vuex 2.0 - github 完整範例
使用 git checkout 切換每天範例。